home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d15 / grafwk50.arc / TSENG.A86 < prev    next >
Text File  |  1991-01-19  |  22KB  |  1,052 lines

  1.         COMMENT %
  2.  
  3.     GRAPHIC WORKSHOP Tseng ET3000/ET4000 SVGA screen driver
  4.     COPYRIGHT (C) 1990 ALCHEMY MINDWORKS INC.
  5.     VERSION 1.1
  6.  
  7.     portions copyright (C) 1990,1991 Gregory D. Weeks
  8.     permision granted for Alchemy Mindworks to distribute.
  9.  
  10.     This driver was adapted from the skeletal driver
  11.     supplied with graphic workshop 3.4.  It will drive
  12.     Tseng ET4000 and ET3000 equipped SVGA cards.  The Tseng
  13.     cards are capable of up to 1024x768 in 256 colors.  This
  14.     driver must be installed after assembly for the
  15.     monitor type.
  16.  
  17.     This driver is designed to be assembled with A86.
  18.  
  19.  
  20.         %
  21.  
  22. VERSION        EQU    1        ;VERSION NUMBER
  23. SUBVERSION      EQU     2               ;SUBVERSION NUMBER
  24.  
  25. _AOFF        EQU    6        ;STACK OFFSET
  26.  
  27. ; these are the maximum possible screen sizes
  28. TLI_WIDE        EQU     1024    ;maximum screen width in pixels
  29. TLI_DEEP        EQU     768     ;maximum screen depth in lines
  30. TLI_SCREENSEG   EQU     0A000H  ;segment of tseng card video buffer
  31. TLI_BYTES       EQU     128     ;maximum width of planar modes in bytes
  32.  
  33.  
  34. ;THIS MACRO SELECTS AN EGA PLANE
  35. EGAPLANE        MACRO
  36.         MOV    AL,2
  37.         MOV    DX,03C4H
  38.         OUT    DX,AL
  39.         INC    DX
  40.         MOV     AL,#1
  41.         OUT    DX,AL
  42.         #EM
  43.  
  44.         ORG     0000H           ;ORIGIN FOR LOADABLE DRIVER
  45.  
  46.         DB    'ALCHDRV2'    ;SIGNATURE - DON'T CHANGE THIS
  47.  
  48. ;THE FOLLOWING ARE THE POINTERS TO THE CALLABLE ROUTINES AND THE COMMON
  49. ;DATA. THE SEGMENTS ARE FILLED IN BY GRAPHIC WORKSHOP. DON'T CHANGE ANYTHING.
  50. DISPATCH:
  51.         DW      VGA_on          ;FAR POINTER TO VGA MODE SELECT
  52.         DW      ?
  53.         DW      VGA_line        ;FAR POINTER TO VGA LINE DISPLAY
  54.         DW    ?
  55.         DW    VGA_OFF        ;FAR POINTER TO VGA MODE DESELECT
  56.         DW    ?
  57.         DW    VGA_PALETTE    ;FAR POINTER TO VGA PALETTE SET
  58.         DW    ?
  59.         DW    VGA_OVERSCAN    ;FAR POINTER TO VGA OVERSCAN SET
  60.         DW    ?
  61.         DW      EGA_ON        ;FAR POINTER TO EGA MODE SELECT
  62.         DW      ?
  63.         DW    EGA_LINE    ;FAR POINTER TO EGA LINE DISPLAY
  64.         DW    ?
  65.         DW    EGA_OFF        ;FAR POINTER TO EGA MODE DESELECT
  66.         DW    ?
  67.         DW    EGA_PALETTE    ;FAR POINTER TO EGA PALETTE SET
  68.         DW    ?
  69.         DW      MONO_ON        ;FAR POINTER TO MONO MODE SELECT
  70.         DW      ?
  71.         DW    MONO_FRAME    ;FAR POINTER TO MONO PAGE DISPLAY
  72.         DW    ?
  73.         DW    MONO_LINE    ;FAR POINTER TO MONO LINE DISPLAY
  74.         DW    ?
  75.         DW    MONO_OFF    ;FAR POINTER TO MONO MODE DESELECT
  76.         DW    ?
  77.         DW    0,0        ;NULL ONE
  78.         DW    0,0        ;NULL TWO
  79.         DW    0,0        ;NULL THREE
  80.         DW    0,0        ;NULL FOUR
  81.  
  82. V_VGAWIDE       DW      TLI_WIDE        ;VGA SCREEN WIDTH
  83. V_VGADEEP       DW      TLI_DEEP        ;VGA SCREEN DEPTH
  84. V_VGASCRNSEG    DW      TLI_SCREENSEG   ;VGA SCREEN SEGMENT
  85. V_EGAWIDE       DW      TLI_WIDE        ;EGA SCREEN WIDTH
  86. V_EGADEEP       DW      TLI_DEEP        ;EGA SCREEN DEPTH
  87. V_EGABYTES      DW      TLI_BYTES       ;EGA SCREEN BYTES
  88. V_EGASCRNSEG    DW      TLI_SCREENSEG   ;EGA SCREEN SEGMENT
  89. V_MONOWIDE      DW      TLI_WIDE       ;MONO SCREEN WIDTH
  90. V_MONODEEP      DW      TLI_DEEP       ;MONO SCREEN DEPTH
  91. V_MONOBYTES     DW      TLI_BYTES      ;BYTE WIDTH ON MONOCHROME SCREEN
  92. V_MONOSCRNSEG   DW      TLI_SCREENSEG  ;MONOCHROME SCREEN SEGMENT
  93.  
  94. ;THESE VERSION NUMBERS REFLECT THE DRIVER TEMPLATE VERSION AND THE
  95. ;VERSION OF THE DRIVER ITSELF. YOU CAN CHANGE THE SUBVERSION VALUE
  96. ;TO REFLECT CHANGES IN YOUR DRIVER. THE VERSION VALUE MUST REMAIN
  97. ;UNCHANGED OR GRAPHIC WORKSHOP MAY REJECT YOUR DRIVER.
  98.         DW    VERSION
  99.         DW    SUBVERSION
  100.  
  101. ;THE DESCRIPTION APPEARS IN THE F10 "ABOUT" BOX IN GRAPHIC
  102. ;WORKSHOP WHEN AN EXTERNAL DRIVER IS BEING USED. IT CAN'T
  103. ;EXCEED 24 CHARACTERS AND MUST BE NULL TERMINATED
  104. Card_Type:      DB      'Tseng ET3000/4000',0
  105.  
  106. Installed dw 0
  107.       dw Mode_Pointer
  108.  
  109. ;THIS ROUTINE SELECTS THE VGA 256 COLOUR MODE
  110. ;THE HEIGHT AND WIDTH OF THE IMAGE ARE ON THE STACK - THESE
  111. ;MAY BE USEFUL IF YOU WANT TO PICK ONE OF SEVERAL AVAILABLE
  112. ;MODES BASED ON THE AREA OF THE PICTURE TO BE DISPLAYED
  113. VGA_on:
  114.    call Install
  115.    push bp
  116.    mov bp,sp
  117.    push ds
  118.    mov ds,cs
  119.  
  120.    mov ax,[bp+_AOFF]   ; cols
  121.    mov bx,[bp+_AOFF+2] ; rows
  122.    mov si,w VGA_mode_pointer
  123.    call pick_mode
  124.    mov V_VGAWIDE,ax
  125.    mov V_VGADEEP,bx
  126.  
  127.    mov ax,cx
  128.    int 10h
  129.  
  130.    mov cx,V_VGADEEP     ;depth of screen in the current mode
  131.    sub dx,dx
  132.    mov bx,dx
  133.    mov si,SCREENTABLE
  134.    mov di,Row_seg
  135.    mov [si],dx
  136.    mov [di],bl
  137.    add si,2
  138.    inc di
  139.    dec cx
  140. l2:
  141.    add dx,V_VGAWIDE
  142.    jnc >l1
  143.    inc bl
  144.    or b[di-1],80h
  145. l1:
  146.    mov [si],dx
  147.    mov [di],bl
  148.    add si,2
  149.    inc di
  150.    loop l2
  151.  
  152.    pop ds,bp
  153.    retf
  154.  
  155.  
  156. ;THIS ROUTINE DISPLAYS A VGA LINE
  157. ;THE FIRST ARGUMENT ON THE STACK (2 WORDS) IS A FAR POINTER TO
  158. ;THE LINE. THE SECOND ARGUMENT IS THE LENGTH OF THE LINE IN PIXELS
  159. VGA_line:
  160.    push bp
  161.    mov bp,sp
  162.    push ds
  163.    push es
  164.  
  165.    mov si,[bp + _AOFF + 0]     ;OFFSET OF SOURCE
  166.    mov ds,[bp + _AOFF + 2]     ;SEGMENT OF SOURCE
  167.  
  168.    mov bx,[bp + _AOFF + 6]     ;GET LINE NUMBER
  169.    cmp bx,cs:V_VGADEEP
  170.    jge SHOWVGAX
  171.  
  172.    mov al,cs:[Row_seg + bx]
  173.    shl bx,1
  174.    mov di,cs:[screentable + bx]
  175.    cld
  176.    mov cx,[bp + _AOFF + 4]
  177.    cmp cx,0
  178.    je SHOWVGAX
  179.    cmp cx,cs:V_VGAWIDE
  180.    jl >l1
  181.    mov cx,cs:V_VGAWIDE
  182. l1:
  183.    test al,80h
  184.    jnz > l2
  185.    call select_write_seg
  186.    mov es,cs:V_VGASCRNSEG
  187.    shr cx,1       ;convert to word moves
  188.    jc >l3
  189.    rep movsw
  190.    jmp >l4
  191. l3:
  192.    rep movsw
  193.    movsb
  194. l4:
  195.    jmp SHOWVGAX
  196. ; from here down is for the few lines that cross segment
  197. ; boundary's.  This routine is slower than the previous rep movsw's.
  198. l2:
  199.    call select_write_seg
  200.    mov bl,al
  201.    mov es,cs:V_VGASCRNSEG
  202. l1:
  203.    movsw
  204.    cmp di,0
  205.    jne >l2
  206.    mov al,bl
  207.    inc al
  208.    call select_write_seg
  209. l2:
  210.    dec cx
  211.    cmp cx,2
  212.    je >l5
  213.    loop l1
  214.    jmp >l3
  215. l5:
  216.    movsb
  217. l3:
  218.  
  219. SHOWVGAX:
  220.    pop es,ds,bp
  221.    retf
  222.  
  223.  
  224. ;THIS ROUTINE SETS THE VGA PALETTE
  225. ;THE FIRST ARGUMENT ON THE STACK IS A FAR POINTER TO
  226. ;THE PALETTE DATA. THE SECOND ARGUMENT IS THE NUMBER OF COLOURS.
  227. VGA_PALETTE:
  228.         PUSH    BP
  229.         MOV    BP,SP
  230.         PUSH    DS
  231.  
  232.         MOV    SI,[BP + _AOFF + 0]    ;OFFSET OF SOURCE
  233.         MOV    DS,[BP + _AOFF + 2]    ;SEGMENT OF SOURCE
  234.  
  235.         MOV    CX,[BP + _AOFF + 4]    ;NUMBER OF COLOURS
  236.  
  237.                 CMP    CX,0            ;CHECK FOR NASTIES
  238.         JG    GVP0
  239.         JMP    GVPX
  240.  
  241.         ;WE'LL SET THE PALLETTE USING DIRECT REGISTERS RATHER
  242.         ;THAN A BIOS CALL AS IT LOOKS NICER, however if
  243.         ;gray scale suming is active, we'll use the BIOS
  244.  
  245. GVP0:
  246.    cmp cs:b gray_VGA,0
  247.    je >l2
  248.    push si,cx
  249.    mov es,ds
  250.    mov di,si
  251. l1:
  252.    lodsb
  253.    shr al,1
  254.    shr al,1
  255.    stosb
  256.    lodsb
  257.    shr al,1
  258.    shr al,1
  259.    stosb
  260.    lodsb
  261.    shr al,1
  262.    shr al,1
  263.    stosb
  264.    loop l1
  265.    pop cx,si
  266.    mov dx,si
  267.    mov bx,0
  268.    mov ax,1012h
  269.    int 10h
  270.    jmp GVPX
  271. l2:
  272.         MOV     DX,03C6H
  273.         MOV    AL,0FFH
  274.         OUT    DX,AL
  275.  
  276.         MOV    BX,0
  277.  
  278. GVP1:        PUSH    CX
  279.         MOV    DX,03C8H
  280.         MOV    AL,BL
  281.         INC    BX
  282.         OUT    DX,AL
  283.  
  284.         INC    DX
  285.  
  286.         LODSB
  287.         SHR    AL,1
  288.         SHR    AL,1
  289.         OUT    DX,AL
  290.  
  291.         LODSB
  292.         SHR    AL,1
  293.         SHR    AL,1
  294.         OUT    DX,AL
  295.  
  296.         LODSB
  297.         SHR    AL,1
  298.         SHR    AL,1
  299.         OUT    DX,AL
  300.  
  301.         POP    CX
  302.         LOOP    GVP1
  303.  
  304.  
  305. GVPX:
  306.         POP    DS
  307.         POP    BP
  308.         RETF
  309. gray_VGA db 0
  310.  
  311. ;THIS ROUTINE SETS THE VGA OVERSCAN.
  312. ;THE FIRST STACK ARGUMENT IS THE COLOUR NUMBER.
  313. VGA_OVERSCAN:
  314.         PUSH    BP
  315.         MOV    BP,SP
  316.         MOV    AX,1001H
  317.         MOV    BX,[BP + _AOFF + 0]
  318.         XCHG    BH,BL
  319.         INT    10H
  320.         POP    BP
  321.         RETF
  322.  
  323. ;THIS ROUTINE SELECTS THE EGA 16 COLOUR MODE
  324. ;THE HEIGHT AND WIDTH OF THE IMAGE ARE ON THE STACK - THESE
  325. ;MAY BE USEFUL IF YOU WANT TO PICK ONE OF SEVERAL AVAILABLE
  326. ;MODES BASED ON THE AREA OF THE PICTURE TO BE DISPLAYED
  327. EGA_on:
  328.    call Install
  329.    push bp
  330.    mov bp,sp
  331.    push ds
  332.    mov ds,cs
  333.  
  334.    mov ax,[bp+_AOFF]   ; cols
  335.    mov bx,[bp+_AOFF+2] ; rows
  336.    mov si,w EGA_mode_pointer
  337.    call pick_mode
  338.    mov V_EGAWIDE,ax
  339.    mov V_EGADEEP,bx
  340.  
  341.    add ax,7
  342.    shr ax,1
  343.    shr ax,1
  344.    shr ax,1
  345.    mov V_EGABYTES,AX
  346.  
  347.    mov ax,cx
  348.    int 10h
  349.  
  350.    mov cx,V_EGADEEP     ;depth of screen in the current mode
  351.    sub dx,dx
  352.    mov bx,dx
  353.    mov si,SCREENTABLE
  354.    mov di,Row_seg
  355.    mov [si],dx
  356.    mov [di],bl
  357.    add si,2
  358.    inc di
  359.    dec cx
  360. EGA_on1:
  361.    add dx,V_EGABYTES
  362.    jnc >l1
  363.    inc bl
  364. l1:
  365.    mov [si],dx
  366.    mov [di],bl
  367.    add si,2
  368.    inc di
  369.    loop EGA_on1
  370.  
  371.    pop ds,bp
  372.    retf
  373.  
  374.  
  375. ;THIS ROUTINE DISPLAYS AN EGA LINE
  376. ;THE FIRST ARGUMENT ON THE STACK (2 WORDS) IS A FAR POINTER TO
  377. ;THE LINE. THE SECOND ARGUMENT IS THE LENGTH OF THE LINE IN BYTES
  378. EGA_LINE:
  379.         PUSH    BP
  380.         MOV    BP,SP
  381.         PUSH    DS
  382.         PUSH    ES
  383.  
  384.         MOV    SI,[BP + _AOFF + 0]    ;OFFSET OF SOURCE
  385.         MOV    DS,[BP + _AOFF + 2]    ;SEGMENT OF SOURCE
  386.         MOV     BX,[BP + _AOFF + 6]    ;GET LINE NUMBER
  387.         CMP     BX,cs:V_EGADEEP
  388.         if GE jmp long  SHOWEGAX
  389.  
  390.    mov al,cs:[Row_seg+bx]
  391.    call select_write_seg
  392.  
  393.         SHL    BX,1
  394.         MOV    DI,CS:[SCREENTABLE+BX]
  395.  
  396.         MOV    AX,0A000H
  397.         MOV    ES,AX
  398.         MOV     BX,[BP + _AOFF + 4]     ;LENGTH OF MOVE IN BYTES
  399.  
  400.    shr bx,1  ; convert to word moves
  401.    jc >l3
  402.         MOV     CX,BX
  403.         EGAPLANE    1
  404.         CLD
  405.         PUSH    DI
  406.    rep movsw
  407.         POP    DI
  408.  
  409.         MOV    CX,BX
  410.         EGAPLANE    2
  411.         PUSH    DI
  412.    rep movsw
  413.         POP    DI
  414.  
  415.         MOV    CX,BX
  416.         EGAPLANE    4
  417.         PUSH    DI
  418.    rep movsw
  419.         POP    DI
  420.  
  421.         MOV    CX,BX
  422.         EGAPLANE    8
  423.         PUSH    DI
  424.    rep movsw
  425.         POP    DI
  426.         EGAPLANE        0FH
  427.    jmp >l4
  428. l3:
  429.         MOV     CX,BX
  430.         EGAPLANE    1
  431.         CLD
  432.         PUSH    DI
  433.    rep movsw
  434.    movsb
  435.         POP    DI
  436.  
  437.         MOV    CX,BX
  438.         EGAPLANE    2
  439.         PUSH    DI
  440.    rep movsw
  441.    movsb
  442.         POP    DI
  443.  
  444.         MOV    CX,BX
  445.         EGAPLANE    4
  446.         PUSH    DI
  447.    rep movsw
  448.    movsb
  449.         POP    DI
  450.  
  451.         MOV    CX,BX
  452.         EGAPLANE    8
  453.         PUSH    DI
  454.    rep movsw
  455.    movsb
  456.         POP    DI
  457.         EGAPLANE        0FH
  458. l4:
  459.  
  460. SHOWEGAX:    POP    ES
  461.         POP    DS
  462.         POP    BP
  463.         RETF
  464.  
  465. ;THIS ROUTINE SETS THE EGA PALETTE
  466. ;THE FIRST ARGUMENT ON THE STACK IS A FAR POINTER TO
  467. ;THE PALETTE DATA. THE SECOND ARGUMENT IS THE NUMBER OF COLOURS.
  468. EGA_PALETTE:
  469.         PUSH    BP
  470.         MOV    BP,SP
  471.         PUSH    DS
  472.  
  473.         MOV    SI,[BP + _AOFF + 0]    ;OFFSET OF SOURCE
  474.         MOV    DS,[BP + _AOFF + 2]    ;SEGMENT OF SOURCE
  475.  
  476.         MOV    CX,[BP + _AOFF + 4]    ;NUMBER OF COLOURS
  477.         SUB    BX,BX
  478.                 CMP    CX,16
  479.         JLE    EGA_PALETTE1
  480.         MOV    CX,16
  481.  
  482. EGA_PALETTE1:    MOV    BH,[SI]
  483.         MOV    AX,1000H
  484.         INT    10H
  485.         INC    BL
  486.         INC    SI
  487.         LOOP    EGA_PALETTE1
  488.  
  489.         POP    DS
  490.         POP    BP
  491.         RETF
  492.  
  493.  
  494. ;THIS ROUTINE SELECTS THE 2 COLOUR MODE
  495. ;THE HEIGHT AND WIDTH OF THE IMAGE ARE ON THE STACK - THESE
  496. ;MAY BE USEFUL IF YOU WANT TO PICK ONE OF SEVERAL AVAILABLE
  497. ;MODES BASED ON THE AREA OF THE PICTURE TO BE DISPLAYED
  498. MONO_on:
  499.    call Install
  500.    push bp
  501.    mov bp,sp
  502.    push ds
  503.    mov ds,cs
  504.  
  505.    mov ax,[bp+_AOFF]   ; cols
  506.    mov bx,[bp+_AOFF+2] ; rows
  507.    mov si,w MONO_mode_pointer
  508.    call pick_mode
  509.    mov V_MONOWIDE,ax
  510.    mov V_MONODEEP,bx
  511.  
  512.    add ax,7
  513.    shr ax,1
  514.    shr ax,1
  515.    shr ax,1
  516.    mov V_MONOBYTES,AX
  517.  
  518.    mov ax,cx
  519.    int 10h
  520.  
  521.    mov cx,V_MONODEEP     ;depth of screen in the current mode
  522.    sub dx,dx
  523.    mov bx,dx
  524.    mov si,SCREENTABLE
  525.    mov di,Row_seg
  526.    mov [si],dx
  527.    mov [di],bl
  528.    add si,2
  529.    inc di
  530.    dec cx
  531. MONO_on1:
  532.    add dx,V_MONOBYTES
  533.    jnc >l1
  534.    inc bl
  535. l1:
  536.    mov [si],dx
  537.    mov [di],bl
  538.    add si,2
  539.    inc di
  540.    loop MONO_on1
  541.  
  542.    pop ds,bp
  543.    retf
  544.  
  545.  
  546.  
  547. UPDATE_MOVE    EQU    2
  548. UPDATE_PAD    EQU    4
  549. UPDATE_ADJUST    EQU    6
  550.  
  551. ;THIS ROUTINE DISPLAYS A FULL MONOCHROME PAGE
  552. ;THE FIRST ARGUMENT ON THE STACK IS A FAR POINTER TO THE PAGE
  553. ;THE SECOND ARGUMENT IS THE WIDTH OF THE BITMAP (IN BYTES)
  554. ;THE THIRD ARGUMENT IS THE NUMBER OF LINES TO DISPLAY
  555. ;NOTE: THE SOURCE BUFFER MAY BE BIGGER THAN 64K.
  556. MONO_FRAME:
  557.         PUSH    BP
  558.         MOV    BP,SP
  559.         SUB    SP,UPDATE_ADJUST
  560.         PUSH    DS
  561.         PUSH    ES
  562.  
  563.         MOV     AX,cs:V_MONOSCRNSEG       ;POINT TO THE SCREEN
  564.         MOV    ES,AX
  565.         MOV    AX,[BP + _AOFF + 4]        ;GET THE WIDTH OF MOVE
  566.         MOV    [BP - UPDATE_MOVE],AX    ;SAVE IT LOCALLY
  567.         MOV    WORD PTR [BP - UPDATE_PAD],0    ;SET ADJUSTMENT
  568.  
  569.         CMP     AX,cs:V_MONOBYTES           ;IF THE MOVE IS LESS THAN
  570.         JL    UPDATE0            ;SCREEN WIDTH, GO FOR IT
  571.  
  572.         SUB     AX,cs:V_MONOBYTES           ;ELSE, SET MOVE WIDTH
  573.         MOV    [BP - UPDATE_PAD],AX    ;...AND THE AMOUNT TO
  574.  
  575.         MOV     AX,cs:V_MONOBYTES           ;...ADJUST THE POINTER
  576.         MOV    [BP - UPDATE_MOVE],AX    ;...AFTER EACH LINE
  577.  
  578. UPDATE0:    MOV    SI,[BP + _AOFF + 0]    ;OFFSET OF BITMAP
  579.         MOV    DS,[BP + _AOFF + 2]    ;SEGMENT OF BITMAP
  580.         MOV    CX,[BP + _AOFF + 6]    ;NUMBER OF LINES
  581.  
  582.         CLD                ;CLEAR DIRECTION FLAG
  583.         SUB    BX,BX
  584.  
  585. UPDATE1:        PUSH    CX                      ;SAVE COUNT (LINE NUMBER)
  586.  
  587.    shr bx,1                ;select the proper segment for the line
  588.    mov al,cs:[Row_seg+bx]  ; actually only needed for the 1024x768 mode
  589.    shl bx,1                ; but it's only done once per line and it's
  590.    call select_write_seg   ; fairly quick so I didn't add the extra code
  591.                ; to bypass it in the other modes
  592.  
  593.         MOV    DI,CS:[SCREENTABLE + BX]
  594.         ADD    BX,2            ;POINT TO NEXT LINE
  595.  
  596.         MOV     CX,[BP - UPDATE_MOVE]   ;GET THE MOVE SIZE
  597.  
  598.    shr cx,1  ; convert to word moves
  599.    jc >l3
  600.    rep movsw
  601.    jmp >l4
  602. l3:
  603.    rep movsw
  604.    movsb
  605. l4:
  606.  
  607.         ADD    SI,[BP - UPDATE_PAD]    ;ADJUST THE POINTER
  608.  
  609.         CMP    SI,0F800H        ;ARE WE WITHIN 2K OF TOP?
  610.         JL      UPDATE2            ;IF NOT, CARRY ON
  611.  
  612.         MOV    AX,SI            ;SEE HOW MANY SEGMENTS ARE
  613.         MOV    CL,4            ;...IN SI (SI DIV 4)
  614.         SHR    AX,CL
  615.  
  616.         MOV    CX,DS            ;ADD THEM TO THE DATA SEGMENT
  617.         ADD    CX,AX            ;...(YOU CAN'T JUST ADD DS,AX)
  618.         MOV    DS,CX
  619.         AND    SI,000FH        ;ADJUST SI (SI MOD 16)
  620.  
  621. UPDATE2:    POP    CX            ;GET COUNT BACK
  622.         LOOP    UPDATE1                    ;DECREMENT AND LOOP
  623.  
  624.         POP    ES
  625.         POP    DS
  626.  
  627.         ADD    SP,UPDATE_ADJUST
  628.         POP    BP
  629.  
  630.         RETF
  631.  
  632. ;THIS ROUTINE DISPLAYS A SINGLE MONOCHROME LINE
  633. ;THE FIRST ARGUMENT ON THE STACK IS A FAR POINTER TO THE LINE
  634. ;THE SECOND ARGUMENT IS THE LINE NUMBER
  635. ;THE THIRD ARGUMENT IS THE WIDTH OF THE BITMAP (IN BYTES)
  636. MONO_LINE:
  637.         PUSH    BP
  638.         MOV    BP,SP
  639.  
  640.         PUSH    DS
  641.         PUSH    ES
  642.  
  643.         MOV     AX,cs:V_MONOSCRNSEG       ;POINT TO THE SCREEN
  644.         MOV    ES,AX
  645.  
  646.         MOV    CX,[BP + _AOFF + 6]        ;GET THE WIDTH OF MOVE
  647.         CMP    CX,0
  648.         JE    MONO_LINE2
  649.         CMP     CX,cs:V_MONOBYTES
  650.         JL    MONO_LINE1
  651.         MOV     CX,cs:V_MONOBYTES
  652.  
  653. MONO_LINE1:    MOV    SI,[BP + _AOFF + 0]    ;OFFSET OF BITMAP
  654.         MOV    DS,[BP + _AOFF + 2]    ;SEGMENT OF BITMAP
  655.         MOV     BX,[BP + _AOFF + 4]     ;NUMBER OF LINE
  656.  
  657.    mov al,cs:[Row_seg+bx]
  658.    call select_write_seg
  659.  
  660.         SHL    BX,1
  661.  
  662.         CLD                ;CLEAR DIRECTION FLAG
  663.         MOV     DI,CS:[SCREENTABLE + BX]
  664.  
  665.    shr cx,1  ; convert to word moves
  666.    jc >l3
  667.    rep movsw
  668.    jmp >l4
  669. l3:
  670.    rep movsw
  671.    movsb
  672. l4:
  673.  
  674. MONO_LINE2:    POP    ES
  675.         POP    DS
  676.  
  677.         POP    BP
  678.         RETF
  679.  
  680. ; this routine selects text mode
  681. VGA_off:
  682. EGA_off:
  683. Mono_off:
  684.    mov ax,0003h
  685.    int 10h
  686.    retf
  687. ;
  688. ;
  689. ; this is the installation routine
  690. Install:
  691.    jmp cs:[Install_Pointer]
  692. Install_it:
  693.    call find_chip
  694.    call find_mem_size
  695.    mov ax,near_return
  696.    mov cs:Install_Pointer,ax
  697. ; test for gray scale summing
  698.    mov ax,1b00h
  699.    mov es,cs
  700.    mov di,screentable
  701.    mov bx,0
  702.    int 10h
  703.    mov al,es:[screentable+2dh]
  704.    and al,00000010xb
  705.    mov cs:gray_VGA,al
  706.    ret
  707. ;
  708.    even
  709. Install_Pointer dw Install_it
  710. ;
  711. ;  these are the segment selection routines
  712. select_write_seg_a dw select_4_write_seg
  713. select_read_seg_a dw select_4_read_seg
  714. ;
  715. select_write_seg:
  716.    jmp cs:[select_write_seg_a]
  717. ;
  718. select_read_seg:
  719.    jmp cs:[select_read_seg_a]
  720. ;
  721. select_no_segment_mode:
  722.    push ax
  723.    mov ax,near_return
  724.    mov cs:select_write_seg_a,ax
  725.    mov cs:select_read_seg_a,ax
  726.    pop ax
  727. near_return:
  728.    ret
  729. ;
  730. select_3_mode:
  731.    push ax
  732.    mov ax,select_3_write_seg
  733.    mov cs:select_write_seg_a,ax
  734.    mov ax,select_3_read_seg
  735.    mov cs:select_read_seg_a,ax
  736.    pop ax
  737.    ret
  738. ;
  739. select_4_mode:
  740.    push ax
  741.    mov ax,select_4_write_seg
  742.    mov cs:select_write_seg_a,ax
  743.    mov ax,select_4_read_seg
  744.    mov cs:select_read_seg_a,ax
  745.    pop ax
  746.    ret
  747. ;
  748. GDC_seg_sel equ 03cdh
  749. ;
  750. select_3_write_seg:
  751.    push ax,dx
  752.    and al,7
  753.    mov ah,al
  754.    mov dx,GDC_seg_sel
  755.    in al,dx
  756.    and al,00111000xb
  757.    or al,01000000xb
  758.    or al,ah
  759.    out dx,al
  760.    pop dx,ax
  761.    ret
  762. ;
  763. select_3_read_seg:
  764.    push ax,dx
  765.    and al,7
  766.    mov ah,al
  767.    mov dx,GDC_seg_sel
  768.    in al,dx
  769.    and al,00000111xb
  770.    or al,01000000xb
  771.    shl ah,1
  772.    shl ah,1
  773.    shl ah,1
  774.    or al,ah
  775.    out dx,al
  776.    pop dx,ax
  777.    ret
  778. ;
  779. select_4_write_seg:
  780.    push ax,dx
  781.    and al,0fh
  782.    mov ah,al
  783.    mov dx,GDC_seg_sel
  784.    in al,dx
  785.    and al,0f0h
  786.    or al,ah
  787.    out dx,al
  788.    pop dx,ax
  789.    ret
  790. ;
  791. select_4_read_seg:
  792.    push ax,dx
  793.    and al,0fh
  794.    mov ah,al
  795.    mov dx,GDC_seg_sel
  796.    in al,dx
  797.    and al,0fh
  798.    shl ah,1
  799.    shl ah,1
  800.    shl ah,1
  801.    shl ah,1
  802.    or al,ah
  803.    out dx,al
  804.    pop dx,ax
  805.    ret
  806. ;
  807. ;  these routines test chip type and memory size
  808. fill_seg_test:
  809.    push cx
  810.    mov cx,80h  ; use 128 bytes to flush the cache
  811.    mov di,0
  812.    cld
  813.    rep stosb
  814.    pop cx
  815.    ret
  816. ;
  817. ;  returns 0123h in ax if segments are selecting properly
  818. test_for_memory:
  819.    push bx,cx,dx,es,di
  820.    mov ax,TLI_screenseg
  821.    mov es,ax
  822. l1:
  823.    call select_write_seg
  824.    call fill_seg_test
  825.    inc al
  826.    cmp al,3
  827.    jng l1
  828.    mov al,0
  829.    call select_read_seg
  830.    mov bl,es:[0]   ;segment 0
  831.    inc al
  832.    call select_read_seg
  833.    mov bh,es:[0]   ;segment 1
  834.    inc al
  835.    call select_read_seg
  836.    mov dl,es:[0]   ;segment 2
  837.    inc al
  838.    call select_read_seg
  839.    mov dh,es:[0]   ;segment 3
  840.    mov cx,4
  841.    shl bl,cl
  842.    or bh,bl
  843.    mov cx,4
  844.    shl dl,cl
  845.    or dh,dl
  846.    mov ah,bh
  847.    mov al,dh
  848.    pop di,es,dx,cx,bx
  849.    ret
  850. ;
  851. find_chip:
  852.    mov ax,002dh ;  a common mode that uses more than 64k
  853.    int 10h
  854.    call select_3_mode
  855.    call test_for_memory
  856.    cmp ax,0123h
  857.    jne >l1
  858.   ; chip is an ET3000
  859.    mov ax,cs:[VGA_lock_table+2]
  860.    cmp ax,400
  861.    jne >l3
  862.    mov ax,350
  863.    mov cs:[VGA_lock_table+2],ax
  864.    mov ax,2dh
  865.    mov cs:[VGA_lock_table+8],ax
  866. l3:
  867.    mov ax,cs:[VGA_mode_table+12]
  868.    cmp ax,400
  869.    jne >l3
  870.    mov ax,350
  871.    mov ax,cs:[VGA_mode_table+12]
  872.    mov ax,2dh
  873.    mov cs:[VGA_mode_table+18],ax
  874. l3:
  875.    jmp >l2
  876. l1:
  877.    call select_4_mode
  878.    call test_for_memory
  879.    cmp ax,0123h
  880.    jne >l1
  881.   ; chip is an ET4000
  882.    jmp >l2
  883. l1:
  884.   ; chip type is unknown  select no paging
  885.    call select_no_segment_mode
  886. l2:
  887.    ret
  888. ;
  889. ; this routine finds the memory size on the card
  890. ; for  1024k check page F
  891. ;      512k        page 7
  892. ;      256k        page 3
  893. ;      64k         page 0  (assumed if other pages aren't there)
  894. find_mem_size:
  895.    push ds,es
  896.    mov ds,cs
  897.    mov ax,TLI_screenseg
  898.    mov es,ax
  899.    mov ax,000fh
  900.    mov cx,ax
  901. l1:
  902.    call select_write_seg
  903.    call fill_seg_test
  904.    dec al
  905.    cmp al,0ffh
  906.    loop l1
  907.    mov al,0fh
  908.    call select_read_seg
  909.    mov bl,es:[0]
  910.    cmp bl,0fh
  911.    jne >l1
  912.    mov bl,3
  913.    jmp >l5
  914. l1:
  915.    mov al,7
  916.    call select_read_seg
  917.    mov bl,es:[0]
  918.    cmp bl,7
  919.    jne >l1
  920.    mov bl,2
  921.    jmp >l5
  922. l1:
  923.    mov al,3
  924.    call select_read_seg
  925.    mov bl,es:[0]
  926.    cmp bl,3
  927.    jne >l1
  928.    mov bl,1
  929.    jmp >l5
  930. l1:
  931.    mov bl,0
  932. l5:
  933.    mov ax,Installed
  934.    mov al,bl
  935.    mov Installed,ax
  936.    pop es,ds
  937.    ret
  938. ;
  939. ;
  940. ;this part goes through all available modes to try to find one that is
  941. ; larger than the picture or the same size as the picture.
  942. pick_mode:
  943.    mov di,si
  944. l3:
  945.    cmp ax,[si]
  946.    ja >l1
  947.    cmp bx,[si+2]
  948.    jbe >l2
  949. l1:
  950.    add si,10
  951.    cmp w[si],0
  952.    jne l3
  953.    sub si,10
  954. l2:
  955. ; this part goes backwards through the list of modes to make sure the card
  956. ; and monitor can handle the mode.  if the lock mode is something that
  957. ; the hardware can't handle, the mode defaults to the first mode in the
  958. ; table
  959.    mov cx,Installed
  960.    sub dx,dx
  961.    mov dl,ch  ; cx is memory available
  962.    mov ch,dh  ; dx is the monitor
  963. l2:
  964.    cmp cx,[si+4]
  965.    jl >l1
  966.    cmp dx,3
  967.    je >l4  ; any mode monitor
  968.    cmp dx,[si+6]
  969.    je >l4  ; monitor and required are the same
  970.    cmp w[si+6],0
  971.    je >l4  ; VGA monitor is all that's needed
  972. ; this lets an 8514 monitor select the 1024x768 mode if the picture
  973. ; requires an 800x600 mode
  974.    cmp dx,2
  975.    jne >l1  ;not an 8514 monitor
  976.    cmp w[si+6],1
  977.    jne >l1  ;not 800x600 mode
  978.    cmp cx,[si+16]
  979.    jne >l1  ;insufficient memory for 1024x768 mode
  980.    add si,10
  981.    jmp >l4  ;select next mode in table
  982. l1:
  983.    cmp di,si
  984.    jne >l1  ;not a lock mode
  985.    add si,12  ;change from lock mode to first mode in table
  986.    jmp >l4
  987. l1:
  988.    sub si,10
  989.    jmp l2
  990. l4:
  991.    mov ax,[si]
  992.    mov bx,[si+2]
  993.    mov cx,[si+8]
  994.    ret
  995. ;
  996.  
  997.    even
  998.  
  999. ;THIS IS A LINE START LOOKUP TABLE
  1000.  
  1001. SCREENTABLE:     DW      TLI_DEEP DUP(?)        ;LINE START TABLE
  1002. Row_seg: db  TLI_deep dup(?)  ;segments for the lines
  1003.  
  1004. ;These are the modes supported.  the tables have the format:
  1005. ;   columns,rows,memory,monitor,mode
  1006. ; where memory is   0   64k    standard VGA
  1007. ;                   1   256k
  1008. ;                   2   512k
  1009. ;                   3   1024k
  1010. ;
  1011. ; and monitor is  0  standard VGA
  1012. ;                 1  800x600 capable Multisync
  1013. ;                 2  1024x768 interlace capable 8514 equivalent
  1014. ;                 3  1024x768 interlace capable multisync
  1015. ;
  1016. Mode_Pointer:
  1017. VGA_mode_pointer dw VGA_mode_table
  1018. EGA_mode_pointer dw EGA_mode_table
  1019. Mono_mode_pointer dw Mono_mode_table
  1020. VGA_lock_table:
  1021.    dw  320,200,0,0,13h
  1022.    dw 0
  1023. VGA_mode_table:
  1024.    dw  320,200,0,0,13h
  1025.    dw  640,400,1,0,2fh  ; 640,350,1,0,2DH   for ET3000
  1026.    dw  640,480,2,0,2eh
  1027.    dw  800,600,2,1,30h
  1028.    dw  1024,768,3,2,38h
  1029.    dw  0
  1030. EGA_lock_table:
  1031.    dw  640,480,0,0,12h
  1032.    dw 0
  1033. EGA_mode_table:
  1034.    dw  320,200,0,0,0dh
  1035.    dw  640,200,0,0,0eh
  1036.    dw  640,350,0,0,10h
  1037.    dw  640,480,0,0,12h
  1038.    dw  800,600,1,1,29h
  1039.    dw  1024,768,2,2,37h
  1040.    dw  0
  1041. Mono_lock_table:
  1042.    dw  640,480,0,0,11h
  1043.    dw 0
  1044. Mono_mode_table:
  1045.    dw  320,200,0,0,0dh
  1046.    dw  640,200,0,0,0eh
  1047.    dw  640,350,0,0,10h
  1048.    dw  640,480,0,0,11h
  1049.    dw  800,600,1,1,29h
  1050.    dw  1024,768,2,2,37h
  1051.    dw  0
  1052.